import xlrd2
from common.settings import logger
from typing import List, Optional
from utils.otherUtils.file_control import check_file_path
from common.constant import ExcelHead, ApiInfo, ExcelHandlerErrorInfo, CommonInfo


class ExcelHandler:

    def __init__(self, api_info: dict):
        self.api_info = api_info

    @property
    def test_data_file_path(self) -> Optional[str]:
        return self.api_info.get(ApiInfo.TEST_DATA_FILE_PATH.value)

    @staticmethod
    def is_empty_row(sheet, row_num) -> bool:
        for col in range(sheet.ncols):
            cell_value = sheet.cell_value(row_num, col)
            if cell_value:
                return False
        return True

    def get_excel_data(self) -> List[dict]:

        # 校验测试数据文件路径
        if self.test_data_file_path:
            test_data_file_path = check_file_path(self.test_data_file_path)
        else:
            logger.error(ExcelHandlerErrorInfo.NO_TEST_DATA_FILE_PATH.value)
            raise ValueError(ExcelHandlerErrorInfo.NO_TEST_DATA_FILE_PATH.value)

        # 读取excel文件
        with xlrd2.open_workbook(test_data_file_path) as excel_data:
            try:
                sheet = excel_data.sheet_by_name(CommonInfo.SHEET_NAME.value)
            except Exception as e:
                logger.error(e)
                raise e
            rows = sheet.nrows
            if rows <= 1:
                logger.error(ExcelHandlerErrorInfo.NO_TEST_DATA.value)
                raise ValueError(ExcelHandlerErrorInfo.NO_TEST_DATA.value)

        # 从表头获取需要的字段，并记录其索引
        head_lst = sheet.row_values(0)
        # logger.info(f'表头：{head_lst}')
        head_index_mapping = {}
        for index, head in enumerate(head_lst):
            if head == ExcelHead.DESCRIBE.value:
                head_index_mapping[head] = index
            elif head == ExcelHead.AUTHOR.value:
                head_index_mapping[head] = index
            elif head == ExcelHead.ID.value:
                head_index_mapping[head] = index
            elif head == ExcelHead.SKIP.value:
                head_index_mapping[head] = index
            elif ExcelHead.REQUEST_PARAMS.value in head:
                head_index_mapping[head] = index
            elif head == ExcelHead.SQL.value:
                head_index_mapping[head] = index
            elif ExcelHead.CHECK_POINT.value in head:
                head_index_mapping[head] = index
            elif ExcelHead.UPLOAD_FILE.value in head:
                head_index_mapping[head] = index
        if not head_index_mapping:
            logger.error(ExcelHandlerErrorInfo.NO_NECESSARY_EXCEL_HEAD.value)
            raise ValueError(ExcelHandlerErrorInfo.NO_NECESSARY_EXCEL_HEAD.value)
        # logger.info(f'表头和对应的索引:{head_index_mapping}')

        # 封装数据：sheet中的每一行为一个字典，一个sheet为一个列表
        result = []
        for i in range(1, rows):
            row_data = {}
            if self.is_empty_row(sheet, i):
                continue
            row_value_lst = sheet.row_values(i)
            if row_value_lst[head_index_mapping[ExcelHead.SKIP.value]]:
                continue
            info = {}
            request_params = {}
            check_point = {}
            upload_file = {}
            for head, index in head_index_mapping.items():
                if ExcelHead.REQUEST_PARAMS.value in head:
                    params = head.split('-')[1]
                    request_params[params] = row_value_lst[index]
                elif ExcelHead.SQL.value == head:
                    row_data[ExcelHead.SQL.value] = row_value_lst[index]
                elif ExcelHead.CHECK_POINT.value in head:
                    if row_value_lst[index]:
                        check_point[head] = row_value_lst[index]
                elif ExcelHead.UPLOAD_FILE.value in head:
                    upload_file[head] = row_value_lst[index]
                else:
                    info[head] = row_value_lst[index]
            row_data[CommonInfo.EXCEL_ROW_INFO.value] = info
            row_data[ExcelHead.REQUEST_PARAMS.value] = request_params
            row_data[ExcelHead.CHECK_POINT.value] = check_point
            row_data[ExcelHead.UPLOAD_FILE.value] = upload_file
            result.append(row_data)
        return result


if __name__ == '__main__':
    d = {'testDataFilePath': 'testData/csdn/single_api/articleListTest.xlsx'}
    print(ExcelHandler(d).get_excel_data())
